package com.chenfan.process.util;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.ObjectUtils;

import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * 公共工具类
 *
 * @author wulg
 * @date 2022-04-07
 **/
public class CommonUtil {

    /**
     * 字符数字数组
     */
    public static String[] CHARS = new String[] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
            "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8",
            "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
            "U", "V", "W", "X", "Y", "Z"};

    /**
     * 默认拆分
     * @param str
     * @param separtor
     * @return
     */
    public static List<Long> defaultSplit(String str, String separtor) {
        String[] items = StringUtils.split(str, separtor);
        List<Long> itemList = null;
        if(ArrayUtils.isEmpty(items)) {
            itemList = Collections.singletonList(-1L);
        } else {
            itemList = new ArrayList<>(items.length);
            for(String item : items) {
                itemList.add(Long.valueOf(item));
            }
        }
        return itemList;
    }

    /**
     * 默认List
     * @param sourceList
     * @param <T>
     * @return
     */
    public static <T> List<T> defaultList(List<T> sourceList) {
        if(CollectionUtils.isEmpty(sourceList)) {
            return new ArrayList<>(0);
        }
        return sourceList;
    }

    /**
     * 默认Map
     * @param sourceMap
     * @param <K, V>
     * @return
     */
    public static <K, V> Map<K, V> defaultMap(Map<K, V> sourceMap) {
        if(Objects.isNull(sourceMap) || sourceMap.size() == 0) {
            return new HashMap<>(0);
        }
        return sourceMap;
    }

    /**
     * 获取某月第一天
     * @param date
     * @return
     */
    public static Date getFirstDayOfMonth(Date date, int amount) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        cal.add(Calendar.MONTH, amount);
        return cal.getTime();
    }

    /**
     * 获取某月的第一天
     * @param date
     * @return
     */
    public static String getFirstDayOfMonth(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        return new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime());
    }
    public static String defaultString(JSONObject jsonObject, Object value) {
        if (value == null) {
            return "";
        }
        return org.apache.commons.lang3.StringUtils.defaultString(jsonObject.getString(value.toString()), "");
    }

    /**
     * 获取某月的最后一天
     * @param date
     * @return
     */
    public static String getLastDayOfMonth(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.roll(Calendar.DAY_OF_MONTH, 0);
        return new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime());
    }

    /**
     * 获取消息Key
     * @param billCode
     * @return
     */
    public static String getMessageKey(String billCode) {
        if(org.apache.commons.lang3.StringUtils.isBlank(billCode)) {
            return UUID.randomUUID().toString();
        }
        return org.apache.commons.lang3.StringUtils.joinWith("_", billCode, getShortUuid());
    }

    /**
     * 获取简短的UUID
     * @return
     */
    public static String getShortUuid() {
        StringBuffer shortBuffer = new StringBuffer();
        String uuid = UUID.randomUUID().toString().replace("-", "");
        int[] digit = {8,4,16};
        for (int i = 0; i < digit[0]; i++) {
            String str = uuid.substring(i * digit[1], i * digit[1] + digit[1]);
            int x = Integer.parseInt(str, digit[2]);
            shortBuffer.append(CHARS[x % 0x3E]);
        }
        return shortBuffer.toString();
    }

    /**
     * 获取百分比
     * @param number
     * @param decimals
     * @return
     */
    public static String getPercentage(double number, int decimals) {
        NumberFormat numberFormat = NumberFormat.getPercentInstance();
        numberFormat.setMinimumFractionDigits(decimals);
        return numberFormat.format(number);
    }

    /**
     * 拼接字符串数组
     * @param separator
     * @param arrayStr
     * @return
     */
    public static String joinWith(String separator, String... arrayStr) {
        List<String> list = Arrays.stream(arrayStr).filter(e -> org.apache.commons.lang3.StringUtils.isNotBlank(e)).collect(Collectors.toList());
        return org.apache.commons.lang3.StringUtils.join(list, separator);
    }

    /**
     * 取值
     * @param map
     * @param k
     * @param function
     * @param <K>
     * @param <V>
     * @param <T>
     * @return
     */
    public static <K,V, T> T getValue(Map<K,V> map, K k, Function<V,T> function) {
        if(MapUtils.isEmpty(map)) {
            return null;
        }
        V v =  map.get(k);
        if(Objects.isNull(function) || Objects.isNull(v)) {
            return null;
        }
        return function.apply(v);
    }

    /**
     * 根据条件获取执行值
     * @param condition
     * @param supplier
     * @param <V>
     * @return
     */
    public static <V> V getIfNecessary(boolean condition, Supplier<V> supplier, V defaultValue) {
        if(!condition) {
            return defaultValue;
        }
        return ObjectUtils.defaultIfNull(supplier.get(), defaultValue);
    }

    public static <K,V> boolean containsKey(Map<K,V> map, K k) {
        if(MapUtils.isEmpty(map) || Objects.isNull(k)) {
            return false;
        }
        return map.containsKey(k);
    }

    public static <K,V> V getMapValue(Map<K,V> map, K k) {
        if(!containsKey(map, k)) {
            return null;
        }
        return map.get(k);
    }

    public static <K,V,T> T getMapValue(Map<K,V> map, K k, Function<V, T> function) {
        V v = getMapValue(map, k);
        if(Objects.isNull(v)) {
            return null;
        }
        return function.apply(map.get(k));
    }


    public static <S extends Number, T extends Number> T numberApply(S s, Function<S,T> function) {
        if(Objects.isNull(s) || Objects.isNull(function)) {
            return null;
        }
        return function.apply(s);
    }
}
